package org.ciallo.easytokencore.interceptor;

import org.ciallo.easytokencore.strategy.EasyAnnotationStrategy;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * Easy-Token 注解拦截器实现类
 *
 * <p>核心功能：</p>
 * <ul>
 *   <li>实现Spring MVC请求拦截</li>
 *   <li>处理自定义注解的方法级权限控制</li>
 *   <li>与EasyAnnotationStrategy配合完成注解处理</li>
 *   <li>支持ResponseBodyAdvice进行响应处理</li>
 * </ul>
 *
 * <p>拦截流程：</p>
 * <ol>
 *   <li>preHandle: 方法执行前进行注解检查</li>
 *   <li>beforeBodyWrite: 方法执行后、响应返回前处理</li>
 *   <li>afterCompletion: 请求完成后清理资源</li>
 * </ol>
 *
 * <p>实现原理：</p>
 * <ul>
 *   <li>通过实现HandlerInterceptor接口实现请求拦截</li>
 *   <li>通过ResponseBodyAdvice接口实现响应处理</li>
 *   <li>委托EasyAnnotationStrategy执行具体注解逻辑</li>
 * </ul>
 *
 * <p>配置方法：</p>
 * <pre>
 * {@code
 * @Configuration
 * public class WebConfig implements WebMvcConfigurer {
 *     @Autowired
 *     private EasyAnnotationInterceptor interceptor;
 *
 *     @Override
 *     public void addInterceptors(InterceptorRegistry registry) {
 *         registry.addInterceptor(interceptor)
 *             .addPathPatterns("/**");
 *     }
 * }
 * }
 * </pre>
 *
 * @Description: Easy-Token 注解拦截器实现类
 * @Author: Jukomu
 * @Package: org.ciallo.easytokencore.interceptor
 * @Project: easy-token-demo
 * @Version: 1.1.0
 * @name: EasyAnnotationInterceptor
 * @Date: 2025-05-17
 * @Filename: EasyAnnotationInterceptor
 * @see org.springframework.web.servlet.HandlerInterceptor
 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice
 * @see EasyAnnotationStrategy
 */
@Component
@ControllerAdvice
public class EasyAnnotationInterceptor implements HandlerInterceptor, ResponseBodyAdvice<Object> {
    /**
     * 请求方法前执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 这里必须确保 handler 是 HandlerMethod 类型时，才能进行注解鉴权
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            EasyAnnotationStrategy.instance.checkMethodAnnotationPreHandle(method);
        }
        return true;
    }

    /**
     * 请求方法完成时执行
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 这里必须确保 handler 是 HandlerMethod 类型时，才能进行注解鉴权
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            EasyAnnotationStrategy.instance.checkMethodAnnotationAfterCompletion(method);
        }
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 确保 method 不为null，才能进行处理
        Method method = returnType.getMethod();
        return method != null;
    }

    /**
     * 请求方法处理完成后、视图渲染之前执行
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        Method method = returnType.getMethod();
        EasyAnnotationStrategy.instance.checkMethodAnnotationPostHandle(method);
        return body;
    }
}
